/*
 * Copyright 2008-2023 dexian.vip. All rights reserved.
 * Support: http://www.dexian.vip
 * License: http://www.dexian.vip/license
 */

package vip.dexian.core.base.bean;

import vip.dexian.core.base.validation.group.Update;
import vip.dexian.core.entity.listener.EntityListener;
import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.Column;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.MappedSuperclass;
import jakarta.persistence.Transient;
import jakarta.persistence.Version;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.SuperBuilder;
import org.hibernate.annotations.Comment;
import org.hibernate.annotations.GenericGenerator;

import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;

/**
 * 实体类基类
 *
 * @author 挺好的 2023年05月30日 8:33
 */
@EntityListeners (EntityListener.class)
@MappedSuperclass
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder
public abstract class BaseEntity<ID extends Serializable> implements Serializable {

    @Serial
    private static final long serialVersionUID = -4060502251790872392L;

    /**
     * id属性名称
     */
    public static final String ID_PROPERTY_NAME = "id";

    /**
     * 创建时间
     */
    public static final String CREATE_DATE_PROPERTY_NAME = "createDate";

    /**
     * 修改时间
     */
    public static final String MODIFY_DATE_PROPERTY_NAME = "modifyDate";

    /**
     * 版本
     */
    public static final String VERSION_PROPERTY_NAME = "version";

    /**
     * 是否有效
     */
    public static final String IS_VALID_PROPERTY_NAME = "isValid";

    /**
     * 使用@Where注解为每个实体类查询的时候添加查询语句。 此时查询出is_valid=1表示有效
     */
    public static final String IS_VALID_WHERE = "is_valid=1";

    /**
     * ID，此处使用mysql数据库，所以指定GenericGenerator为native(自定义主键生成策略)由底层数据库完成
     * <p>
     * GeneratedValue (strategy = GenerationType.AUTO, generator = "sequenceGenerator") 使用oracle序列
     */
    @Comment ("ID")
    @Id
    @GeneratedValue (strategy = GenerationType.AUTO, generator = "native")
    @GenericGenerator (name = "native")
    @NotNull (message = "ID不能为空", groups = Update.class)
    private ID id;

    /**
     * 创建时间
     */
    @Comment ("创建时间")
    @Column (nullable = false, updatable = false)
    private LocalDateTime createDate;

    /**
     * 修改时间
     */
    @Comment ("修改时间")
    @Column (nullable = false)
    private LocalDateTime modifyDate;

    /**
     * 版本号
     */
    @Version
    @Comment ("版本号")
    @Column (nullable = false)
    @JsonIgnore
    private Long version;

    /**
     * 是否有效
     */
    @Comment ("是否有效。1：有效，0：无效")
    @Column (nullable = false)
    @JsonIgnore
    private Boolean isValid;

    /**
     * 是否是新的对象
     *
     * @return 当id == null 的时候，返回true，否则返回false
     */
    @Transient
    @JsonIgnore
    public boolean isNew () {
        return this.getId() == null;
    }

    /**
     * 重写equals，只根据ID来判断是否相等
     *
     * @param obj
     *         比较的对象
     *
     * @return 是否equals
     */
    @Override
    public boolean equals (Object obj) {
        if (obj == null) {
            return false;
        }

        if (this == obj) {
            return true;
        }

        if (!BaseEntity.class.isAssignableFrom(obj.getClass())) {
            return false;
        }

        BaseEntity <?> other = (BaseEntity <?>) obj;

        if (this.getId() == null) {
            return false;
        }

        return this.getId().equals(other.getId());
    }

    /**
     * @return hashcode
     */
    @Override
    public int hashCode () {
        int hashCode = 17;
        hashCode += this.getId() != null ? this.getId().hashCode() * 31 : 0;
        return hashCode;
    }
}
